package com.ddyx.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.jms.Destination;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ddyx.entity.Booking;
import com.ddyx.entity.EventClickFavorite;
import com.ddyx.entity.EventLog;
import com.ddyx.entity.Goods;
import com.ddyx.entity.Store;
import com.ddyx.entity.WxUser;
import com.ddyx.entity.user.UStore;
import com.ddyx.mapper.BookingMapper;
import com.ddyx.mapper.EventClickFavoriteMapper;
import com.ddyx.mapper.EventLogMapper;
import com.ddyx.mapper.GoodsMapper;
import com.ddyx.mapper.StoreMapper;
import com.ddyx.mapper.WxUserMapper;
import com.ddyx.mapper.user.UStoreMapper;
import com.ddyx.service.BookingService;
import com.ddyx.util.EventTag;
import com.ddyx.util.MD5FileUtil;
import com.ddyx.util.MQUtil;
import com.ddyx.util.MyBeanUtils;
import com.ddyx.util.PropertiesUtil;
import com.ddyx.util.RequestForm;
import com.ddyx.util.ResponseForm;
import com.ddyx.util.template.KeyWord;
import com.ddyx.util.template.TemplateMessageParam;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import lombok.extern.slf4j.Slf4j;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

@Slf4j
@Service
public class BookingServiceImpl implements BookingService {
	private static ObjectMapper jsonMapper = new ObjectMapper();
	@Resource
	BookingMapper bookingMapper;
	@Resource
	GoodsMapper goodsMapper;
	@Resource
	EventLogMapper eventLogMapper;
	@Resource
	WxUserMapper wxUserMapper;
	@Resource
	StoreMapper storeMapper;
	@Resource
	UStoreMapper usMapper;
	@Resource
	EventClickFavoriteMapper ecfMapper;

	@Resource
	JmsTemplate jmsTemplate;
	@Resource
	Destination tmpMsgDestination;
	@Resource
	Destination topicDestination;

	@Transactional
	@SuppressWarnings("unchecked")
	@Override
	public ResponseForm insertBooking(RequestForm param, HttpServletRequest req) throws Exception {
		ResponseForm result = new ResponseForm();
		Booking booking = new Booking();
		String requestUrl = req.getRequestURL().toString();
		Map<String, Object> paramMap = (Map<String, Object>) param.getData();
		List list = new ArrayList<>();
		Map<String, Object> keyword = new HashMap<>();// 用于存放模版消息的参数
		TemplateMessageParam tmpMsgParam = new TemplateMessageParam();
		try {
			MyBeanUtils.populate(booking, paramMap);
			booking.setCreateTime(new Date());// 订单生成时间
//			booking.setStatus(0);// 默认预约单状态为1激活状态
			bookingMapper.insertSelective(booking);

			Map<String, Object> map = new HashMap<>();
			map.put("bookingId", booking.getBookingId());

			// 获取单个商品被预约的总数 bookingCount
			Example e = new Example(Booking.class);
			Criteria c = e.createCriteria();
			c.andEqualTo("goodsId", booking.getGoodsId());
			int bookingCount = bookingMapper.selectCountByExample(e);
			map.put("bookingCount", bookingCount);

//			{// 用户新增预约事件同步信息
//				EventLog eventLog = new EventLog();
//				eventLog.setEventTag(EventTag.BOOKING);
//				eventLog.setEventTime(booking.getCreateTime());
//				eventLog.setRequestUrl(requestUrl);
//				eventLog.setStoreNo(booking.getStoreNo());
//				eventLog.setUrlMd5(MD5FileUtil.getMD5String(requestUrl));
//				eventLog.setWxUid(booking.getWxUid());
//				eventLogMapper.insertSelective(eventLog);
//			}

			result.setData(map);
		} catch (Exception e) {
			e.printStackTrace();
			result.setStatus(false);
			result.setMessage("操作有误");
			log.error("操作有误");
		}

		// 模版消息通知
		// 获取openid
		WxUser wxUser = new WxUser();
		wxUser.setWxUid(booking.getWxUid());
		wxUser = wxUserMapper.selectOne(wxUser);
		// 获取门店信息
		/*Store store = new Store();
		store.setStoreNo(booking.getStoreNo());
		store = storeMapper.selectOne(store);*/
		UStore store = new UStore();
		store.setStoreNo(booking.getStoreNo());
		store = usMapper.selectOne(store);
		// 参数
		if (wxUser != null && store != null) {
			list.add(new KeyWord(booking.getGoodsName(), EventTag.BLACK));// 预约商品名
			list.add(new KeyWord(booking.getGoodsPrice(), EventTag.BLACK));// 预约价格
			list.add(new KeyWord(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(booking.getBookingDate()),EventTag.BLACK));// 预约到店时间
			list.add(new KeyWord(booking.getBookerName(), EventTag.BLACK));// 预约人姓名
			list.add(new KeyWord(store.getStoreName(), EventTag.BLACK)); // 门店名
			list.add(new KeyWord(store.getLocation(), EventTag.BLACK)); // 门店地址
			list.add(new KeyWord(store.getStorePhone(), EventTag.BLACK)); // 联系方式
			list.add(new KeyWord("店员会为您提前准备好预约商品,请您在预约时间之前到达门店", EventTag.BLACK)); // 温馨提示

			int i = 1;
			for (Object o : list) {
				keyword.put("keyword" + i, o);
				i++;
			}
			// 设置参数
			tmpMsgParam.setTouser(wxUser.getOpenId());
			tmpMsgParam.setForm_id((String) paramMap.get("formId"));
			tmpMsgParam.setTemplate_id(PropertiesUtil.getProperty(EventTag.BOOKINGTEMP));
			tmpMsgParam.setData(keyword);
			tmpMsgParam.setEmphasis_keyword("keyword1.DATA");
			tmpMsgParam.setPage(PropertiesUtil.getProperty(EventTag.BOOKING_PAGE) + booking.getGoodsId());
			String json = jsonMapper.writeValueAsString(tmpMsgParam);
			// MQ异步发送
			MQUtil.sendJsonMsg(json, jmsTemplate, tmpMsgDestination);
		} else {
			result.setMessage("保存操作成功;由于参数有误,发送通知失败!");
		}
		return result;
	}

	@Transactional
	@SuppressWarnings("unchecked")
	@Override
	public ResponseForm editBooking(RequestForm param, HttpServletRequest req) {
		ResponseForm result = new ResponseForm();
		Booking booking = new Booking();
		String requestUrl = req.getRequestURL().toString();
		Map<String, Object> paramMap = (Map<String, Object>) param.getData();
		try {
			MyBeanUtils.populate(booking, paramMap);
			bookingMapper.updateByPrimaryKeySelective(booking);

//			{// 用户修改预约事件同步信息
//				EventLog eventLog = new EventLog();
//				eventLog.setEventTag(EventTag.EDITBOOKING);
//				eventLog.setEventTime(new Date());// 事件发生更改的时间
//				eventLog.setRequestUrl(requestUrl);
//				eventLog.setStoreNo(booking.getStoreNo());
//				eventLog.setUrlMd5(MD5FileUtil.getMD5String(requestUrl));
//				eventLog.setWxUid(booking.getWxUid());
//				eventLogMapper.insertSelective(eventLog);
//			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setStatus(false);
			result.setMessage("操作有误");
			log.error("操作有误");
		}
		return result;
	}

	@Transactional
	@SuppressWarnings("unchecked")
	@Override
	public ResponseForm cancelBooking(RequestForm param, HttpServletRequest req) {
		ResponseForm result = new ResponseForm();
		Booking booking = new Booking();
		String requestUrl = req.getRequestURL().toString();
		Map<String, Object> paramMap = (Map<String, Object>) param.getData();
		try {
			MyBeanUtils.populate(booking, paramMap);
			booking.setStatus(0);// 假删除,取消时状态改为0
			bookingMapper.updateByPrimaryKeySelective(booking);

//			{// 用户取消预约事件同步信息
//				EventLog eventLog = new EventLog();
//				eventLog.setEventTag(EventTag.CANCELBOOKING);
//				eventLog.setEventTime(booking.getCreateTime());
//				eventLog.setRequestUrl(requestUrl);
//				eventLog.setStoreNo(booking.getStoreNo());
//				eventLog.setUrlMd5(MD5FileUtil.getMD5String(requestUrl));
//				eventLog.setWxUid(booking.getWxUid());
//				eventLogMapper.insertSelective(eventLog);
//			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setStatus(false);
			result.setMessage("操作有误");
			log.error("操作有误");
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	@Override
	public ResponseForm getBooking(RequestForm param) {
		ResponseForm result = new ResponseForm();
		// Booking booking = new Booking();
		Map<String, Object> paramMap = (Map<String, Object>) param.getData();
		try {
			// MyBeanUtils.populate(booking, paramMap);
			paramMap = com.ddyx.util.Page.parsePage(paramMap);
			Page<Object> pageHelper = PageHelper.startPage((int) paramMap.get("page"), (int) paramMap.get("size"));
			// List<Booking> list = bookingMapper.select(booking);
			List<Map<String, Object>> list = bookingMapper.getBooking(paramMap);
			result.setData(list);
			result.setTotal((int) pageHelper.getTotal());
		} catch (Exception e) {
			e.printStackTrace();
			result.setStatus(false);
			result.setMessage("操作有误");
			log.error("操作有误");
		}
		return result;
	}

	/*
	 * 用户查看预约详情页
	 */
	@SuppressWarnings("unchecked")
	@Override
	public ResponseForm getBookingDetails(RequestForm param) {
		ResponseForm result = new ResponseForm();
		Map<String, Object> paramMap = (Map<String, Object>) param.getData();
		try {
			Map<String, Object> map = bookingMapper.getBookingDetails(paramMap);
			result.setData(map);
		} catch (Exception e) {
			e.printStackTrace();
			result.setStatus(false);
			result.setMessage("操作有误");
			log.error("操作有误");
		}
		return result;
	}

	/**
	 * 前端,后端也可以使用 获取所有已经结束的预约(包含以下四种情况) 1: 未赴约未过期未取消(默认) 0:取消预约(此状态为用户控制)
	 * 2:已赴约(此状态为为店员根据用户赴约情况控制) 3:未赴约已过期(此状态为系统自动控制)
	 */
	@Override
	public ResponseForm getOverBooking(RequestForm param) {
		ResponseForm result = new ResponseForm();
		Map<String, Object> paramMap = (Map<String, Object>) param.getData();
		try {
			paramMap = com.ddyx.util.Page.parsePage(paramMap);
			Page<Object> pageHelper = PageHelper.startPage((int) paramMap.get("page"), (int) paramMap.get("size"));
			List<Map<String, Object>> list = bookingMapper.getOverBooking(paramMap);
			result.setData(list);
			result.setTotal((int) pageHelper.getTotal());
		} catch (Exception e) {
			e.printStackTrace();
			result.setStatus(false);
			result.setMessage("操作有误");
			log.error("操作有误");
		}
		return result;
	}

	/*
	 * 编辑预约单接口
	 */
	@Override
	public ResponseForm editBookingStatus(RequestForm param) {
		ResponseForm result = new ResponseForm();
		Map<String, Object> paramMap = (Map<String, Object>) param.getData();
		try {
			int bookingStatus = (int) paramMap.get("bookingStatus");
			Booking booking = new Booking();
			if (bookingStatus == 2 || bookingStatus == 3) {
				booking.setStatus(bookingStatus);
				booking.setBookingId((Integer) paramMap.get("bookingId"));
				bookingMapper.updateByPrimaryKeySelective(booking);
			} else {
				result.setStatus(false);
				result.setMessage("参数有误");
				log.error("参数有误");
			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setStatus(false);
			result.setMessage("操作有误");
			log.error("操作有误");
		}
		return result;
	}

	/*
	 * 清理过期预约单 更改状态为已过期
	 */
	@Override
	public void cleanBooking() {
		bookingMapper.cleanBooking();
	}

	/*
	 * 批量新增多 个预约单
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	@Override
	public ResponseForm insertBookings(RequestForm param, HttpServletRequest req) {
		ResponseForm result = new ResponseForm();
		if (param.getData() != null) {
			try {
				Map paramMap = (Map) param.getData();
				String bookerName = (String) paramMap.get("bookerName");
				String wxUid = (String) paramMap.get("wxUid");
				Date bookingDate = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse((String) paramMap.get("bookingDate"));
				String storeNo = (String) paramMap.get("storeNo");
				String mobile = (String) paramMap.get("mobile");
				String remark = (String) paramMap.get("remark");
				String formId = (String) paramMap.get("formId");
				List goodsIds = (List) paramMap.get("goodsIds");
				String employeNo = (String) paramMap.get("employeNo");
				Date createTime = new Date();
				List<Goods> goodsList = getGoodsList(goodsIds);
				Booking booking = new Booking(wxUid,bookingDate,bookerName,storeNo,mobile,remark,createTime,0,employeNo);
				//批量预约
				massBooking(booking, goodsList);
				//批量删除收藏列表
				removeFavGoods(wxUid, goodsIds);
				
				//事件同步 -------------------------------------------------
				String requestUrl = req.getRequestURL().toString();
				paramMap.put("requestUrl",requestUrl);
				paramMap.put("urlMd5",MD5FileUtil.getMD5String(requestUrl));
				paramMap.put("actionType", EventTag.BOOKING);
				paramMap.put("eventTime", createTime);
				MQUtil.sendObMsg(paramMap, jmsTemplate, topicDestination);
				
				//服务通知-------------------------------------------------
				// 模版消息通知
				// 获取openid
				WxUser wxUser = new WxUser();
				wxUser.setWxUid(wxUid);
				wxUser = wxUserMapper.selectOne(wxUser);
				// 获取门店信息
				/*Store store = new Store();
				store.setStoreNo(storeNo);
				store = storeMapper.selectOne(store);*/
				UStore store = new UStore();
				store.setStoreNo(storeNo);
				store = usMapper.selectOne(store);
				
				Map<String, Object> keyword = new HashMap<>();// 用于存放模版消息的参数
				TemplateMessageParam tmpMsgParam = new TemplateMessageParam();
				// 参数
				List list = new ArrayList<>();
				if (wxUser != null && store != null) {
					list.add(new KeyWord("预约成功"+goodsList.size()+"件商品", EventTag.BLACK));// 预约商品数
					list.add(new KeyWord(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(bookingDate),EventTag.BLACK));// 预约到店时间
					list.add(new KeyWord(bookerName, EventTag.BLACK));// 预约人姓名
					list.add(new KeyWord(store.getStoreName(), EventTag.BLACK)); // 门店名
					list.add(new KeyWord(store.getLocation(), EventTag.BLACK)); // 门店地址
					list.add(new KeyWord(store.getStorePhone(), EventTag.BLACK)); // 联系方式
					list.add(new KeyWord("店员会为您提前准备好预约商品,请您在预约时间之前到达门店", EventTag.BLACK)); // 温馨提示

					int i = 1;
					for (Object o : list) {
						keyword.put("keyword" + i, o);
						i++;
					}
					// 设置参数
					tmpMsgParam.setTouser(wxUser.getOpenId());
					tmpMsgParam.setForm_id(formId);
					tmpMsgParam.setTemplate_id(PropertiesUtil.getProperty(EventTag.MASSBOOKINGTEMP));
					tmpMsgParam.setData(keyword);
					tmpMsgParam.setEmphasis_keyword("keyword1.DATA");
					tmpMsgParam.setPage(PropertiesUtil.getProperty(EventTag.MASSBOOKING_PAGE));
					String json = jsonMapper.writeValueAsString(tmpMsgParam);
					// MQ异步发送
					MQUtil.sendJsonMsg(json, jmsTemplate, tmpMsgDestination);
				} else {
					result.setMessage("保存操作成功;由于参数有误,发送通知失败!");
				}
				
			} catch (Exception e) {
				e.printStackTrace();
				result.setStatus(false);
				result.setMessage("操作有误");
				log.error("操作有误");
			}
			return result;
		}
		return null;
	}

	/**
	 * 批量获取商品信息数据
	 * 
	 * @param goodsIds
	 * @return
	 */
	private List<Goods> getGoodsList(List goodsIds) {
		List<Goods> goodsList = new ArrayList<>();
		if (goodsIds != null) {
			for (Object id : goodsIds) {
				Goods goods = goodsMapper.selectByPrimaryKey(id);
				if(goods!=null) {
					goodsList.add(goods);
				}
			}
		}
		return goodsList;
	}

	/**
	 * 批量 删除 收藏的商品
	 * 
	 * @param wxUid
	 * @param goodsIds
	 */
	private void removeFavGoods(String wxUid, List goodsIds) {
		if (goodsIds != null && StringUtils.isNotBlank(wxUid)) {
			EventClickFavorite bean = new EventClickFavorite();
			for (Object id : goodsIds) {
				bean.setGoodsId((Integer) id);
				bean.setWxUid(wxUid);
				ecfMapper.delete(bean);
			}
		}
	}

	/**
	 * 批量 新增预约
	 * 
	 * @param wxUid
	 * @param os
	 */
	private void massBooking(Booking booking , List<Goods> goodsList) {
		if(booking!=null && goodsList!=null) {
			for (Goods goods : goodsList) {
				booking.setBookingId(null);
				booking.setGoodsId(goods.getGoodsId());
				booking.setGoodsName(goods.getGoodsName());
				booking.setGoodsPic(goods.getGoodsPic());
				booking.setGoodsPrice(goods.getGoodsPrice().toString());
				bookingMapper.insertSelective(booking);
			}
		}
	}

}
